/**
 * @file its-storage 入口
 * @author its-wild(https://gitee.com/its-wild)
 * @date 2022/06/30
 */
import { privateKey, publicKey } from './utils/key.js'
import { WebStorage } from './storage/index'

export type TOptions = {
  /**
   * web存储方式
   */
  storage: 'local' | 'session'

  /**
   * 命名空间
   */
  namespace?: string

  /**
   * window 事件列表
   */
  events?: Array<string>

  /**
   * 公钥加密用
   */
  publicKey?: string

  /**
   * 私钥解密用
   */
  privateKey?: string

  /**
   * 是否加密
   */
  encryption?: boolean
}

export interface IItsStorage {
  options: TOptions
  create: (options?: TOptions) => WebStorage
}

const _global = (typeof window !== 'undefined' ? window : (global as any) || {})

const ItsStorage: IItsStorage = {
  options: {
    storage: 'local',
    namespace: '',
    events: ['storage'],
    publicKey,
    privateKey,
    encryption: false
  },
  /**
   * its-storage 初始化方法，创建一个web存储对象
   * @param {TOptions} options 配置项
   * @returns 存储对象
   */
  create: function (options?: TOptions): WebStorage {
    // 如果要加密并且要使用自己的密钥，那就要求公钥和私钥都要传
    if (options?.encryption === true) {
      if (options.publicKey) {
        if (!options.privateKey) {
          throw new Error(`its-storage: privateKey is must required`)
        }
      }
      if (options.privateKey) {
        if (!options.publicKey) {
          throw new Error(`its-storage: publicKey is must required`)
        }
      }
    }

    // 初始化，合并配置项
    this.options = {
      ...this.options,
      ...options,
    }

    const { storage } = this.options

    // 不是 local、session 其中之一就抛出异常
    if (!['local', 'session'].includes(storage)) {
      throw new Error(`its-storage: Storage "${storage}" is not supported`)
    }

    let store

    switch (storage) {
      case 'local':
        store = 'localStorage' in _global
          ? _global.localStorage
          : null
        break

      case 'session':
        store = 'sessionStorage' in _global
          ? _global.sessionStorage
          : null
        break
    }

    return new WebStorage(this.options, store)
  }
}

_global.ItsStorage = ItsStorage

export default ItsStorage